﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BMWKT
{
	internal class BackupFileToZip 
	{
		private Label _label1;

		private CheckedListBox _checkedListBox1;

		private CheckBox _checkBox1;

		private TextBox _textBox1;

		private string _filePath;


		public BackupFileToZip(Label labelName, CheckBox checkBoxName, TextBox textBoxName, CheckedListBox checkedListBoxName, string filePath)
		{
			_label1 = labelName;
			_checkedListBox1 = checkedListBoxName;
			_checkBox1 = checkBoxName;
			_textBox1 = textBoxName;
			_filePath = filePath;
		}

		public void CreateGameConfigBackupFile()
		{
			string UserSelectedPath = string.Empty;
			using (FolderBrowserDialog folderDialog = new FolderBrowserDialog())
			{
				if (folderDialog.ShowDialog() == DialogResult.OK)
				{
					UserSelectedPath = folderDialog.SelectedPath;
				}
				else
				{
					_label1.Text = "未选择目录！";
					return;
				}
			}

			if (!Directory.Exists(_filePath))
			{
				_label1.Text = "路径不存在！";
				return;
			}

			string selectedSubDirName = "Config";
			string selectedSubDirPath = Path.Combine(_filePath, selectedSubDirName);

			if (!Directory.Exists(selectedSubDirPath))
			{
				_label1.Text = "子目录不存在！";
				return;
			}

			string timeStamp = DateTime.Now.ToString("yyyyMMdd-HHmmss");

			string zipFileName;

			if (_checkBox1.Checked)
			{
				if (string.IsNullOrEmpty(_textBox1.Text))
				{
					_label1.Text = "自定义备份名称不能为空!";
					return;
				}
				zipFileName = $"{_textBox1.Text}.zip";
			}
			else
			{
				zipFileName = $"{selectedSubDirName}_{timeStamp}.zip";
			}
			string zipFilePath = Path.Combine(UserSelectedPath, zipFileName);

			try
			{
				CreateZipFile(selectedSubDirPath, zipFilePath);
				_label1.Text = $"用户配置手动备份成功！\n\n备份文件路径：{UserSelectedPath}\\{zipFilePath}";
				RecordBackupInfo(zipFileName, zipFilePath, "玩家配置");
			}
			catch (Exception ex)
			{
				_label1.Text = $"备份失败: {ex.Message}";
			}
		}

		public void CreateGameSavedBackupFile() 
		{
			string UserSelectedPath = string.Empty;
			using (FolderBrowserDialog folderDialog = new FolderBrowserDialog())
			{
				if (folderDialog.ShowDialog() == DialogResult.OK)
				{
					UserSelectedPath = folderDialog.SelectedPath;
				}
				else
				{
					_label1.Text = "未选择目录！";
					return;
				}
			}

			if (!Directory.Exists(_filePath))
			{
				_label1.Text = "路径不存在！";
				return;
			}

			string selectedSubDirName = _checkedListBox1.Text;
			string selectedSubDirPath = Path.Combine(_filePath, selectedSubDirName);

			if (!Directory.Exists(selectedSubDirPath))
			{
				_label1.Text = "子目录不存在！";
				return;
			}

			string timeStamp = DateTime.Now.ToString("yyyyMMdd-HHmmss");

			string zipFileName;

			if (_checkBox1.Checked)
			{
				if (string.IsNullOrEmpty(_textBox1.Text))
				{
					_label1.Text = "自定义备份名称不能为空!";
					return;
				}
				zipFileName = $"{_textBox1.Text}.zip";
			}
			else
			{
				zipFileName = $"{selectedSubDirName}_{timeStamp}.zip";
			}
			string zipFilePath = Path.Combine(UserSelectedPath, zipFileName);

			try
			{
				CreateZipFile(selectedSubDirPath, zipFilePath);
				_label1.Text = $"存档手动备份成功！\n\n存档备份路径：{UserSelectedPath}\\{zipFilePath}";
				RecordBackupInfo(zipFileName, zipFilePath, "玩家存档");
			}
			catch (Exception ex)
			{
				_label1.Text = $"备份失败: {ex.Message}";
			}
		}

		public void CreateZipFile(string selectedSubDirPath,string zipFilePath) 
		{
			// 备份为zip文件
			ZipFile.CreateFromDirectory(selectedSubDirPath, zipFilePath);
			Process.Start("explorer.exe", $"/select,\"{zipFilePath}\"");
		}

		public string CalculateMD5(string filePath)
		{
			using (var md5 = MD5.Create())
			{
				using (var stream = File.OpenRead(filePath))
				{
					byte[] hash = md5.ComputeHash(stream);
					return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
				}
			}
		}

		public string GetFileSizeString(long size)
		{
			string[] sizeSuffixes = { "字节", "KB", "MB", "GB", "TB" };
			double readableSize = size;
			int order = 0;

			while (readableSize >= 1024 && order < sizeSuffixes.Length - 1)
			{
				order++;
				readableSize /= 1024;
			}

			return $"{readableSize:F2} {sizeSuffixes[order]}";
		}

		public void RecordBackupInfo(string zipFileName, string zipFilePath,string bT)
		{
			try
			{
				// 获取文件大小
				long fileSize = new FileInfo(zipFilePath).Length;
				string fileSizeReadable = GetFileSizeString(fileSize);

				// 获取文件创建时间
				DateTime creationTime = File.GetCreationTime(zipFilePath);

				// 计算文件的 MD5 值
				string fileMD5 = CalculateMD5(zipFilePath);
				string selectedSubDirName = _checkedListBox1.Text;
				string selectedSubDirPath = Path.Combine(_filePath, selectedSubDirName);
				new WriteGameSavedBackupInfo(
					zipFileName, // 存档名称
					fileSizeReadable,                              // 存档大小
					fileMD5,                                       // 存档MD5
					creationTime.ToString("yyyy年MM月dd日HH时mm分ss秒"),  // 备份时间
					zipFilePath,                                    // 备份路径
					selectedSubDirPath,
					bT
				);

			}
			catch (Exception ex)
			{
				_label1.Text = $"备份信息记录失败: {ex.Message}";
			}
		}

	}

	internal class ChangeBackColor 
	{
		private static Color panelOldColor;

		public static void SetPanelNewColor(Panel panelName) 
		{
			panelOldColor = panelName.BackColor;
			panelName.BackColor = Color.PaleTurquoise;
		}

		public static void SetPanelOldColor(Panel panelName)
		{
			panelName.BackColor = panelOldColor;
		}
	}

	internal class CreateAboutProgramUI
	{
		public CreateAboutProgramUI()
		{
			FormManager.CreateForm("AboutProgram");
		}
	}

	internal class CreateGameConfigSavedManageUI
	{
		public CreateGameConfigSavedManageUI()
		{
			FormManager.CreateForm("GameConfigSaved");
		}
	}

	internal class CreateGameSavedManageUI 
	{
		public CreateGameSavedManageUI() 
		{
			FormManager.CreateForm("GameSaved");
		}
	}

	internal class CreateGameModManageUI
	{
		public CreateGameModManageUI()
		{
			FormManager.CreateForm("GameMod");
		}
	}

	internal class FormManager
	{
		// 用字典存储已经创建的窗体，键是窗体的名称，值是窗体的实例
		private static Dictionary<string, Form> _createdForms = new Dictionary<string, Form>();

		// 创建窗体，如果已存在则不再创建
		public static void CreateForm(string formName)
		{
			if (_createdForms.ContainsKey(formName))
			{
				// 如果窗体已存在且未被销毁，则显示它
				Form existingForm = _createdForms[formName];

				// 检查窗体是否已经被销毁
				if (existingForm.IsDisposed)
				{
					// 如果窗体已经销毁，则创建一个新的窗体
					existingForm = CreateNewForm(formName);
					_createdForms[formName] = existingForm;
				}

				existingForm.Show();
			}
			else
			{
				// 如果窗体不存在，则创建一个新窗体并保存
				Form newForm = CreateNewForm(formName);
				if (newForm != null)
				{
					_createdForms[formName] = newForm;
					newForm.Show();
				}
			}
		}

		// 根据窗体名称创建不同的窗体
		private static Form CreateNewForm(string formName)
		{
			switch (formName)
			{
				case "GameSaved":
					return new GameSaved();
				case "GameMod":
					return new GameMod();
				case "GameConfigSaved":
					return new GameConfigSaved();
				case "AboutProgram":
					return new AboutProgram();
				// 可以在这里添加更多的窗体创建逻辑
				default:
					return null;
			}
		}
	}

	internal class GetBMWKInstallPathForProcess
	{
		public static bool IsUserGameConfig { get; set; }

		public static bool IsGetInstallPath { get; set; }

		public static string InstallPath { get; set; }

		public static string GameModPath { get; set; }

		public static string GameSavedPath { get; set; }

		public static string GameConfigSavedPath { get; set; }

		public static string GameFileLastModifiedTime { get; set; }

		public static string GameFileMD5 { get; set; }

		public GetBMWKInstallPathForProcess() 
		{
			GameConfigSavedPath = GetUserGameConfigSavedPath();
			InstallPath = GetInstallPath();
			if (IsGetInstallPath)
			{
				GameModPath = Path.Combine(InstallPath, "b1", @"Binaries\Win64");
				GameSavedPath = Path.Combine(InstallPath, "b1", "Saved");
				GameFileLastModifiedTime = GetFileLastModifiedTime().ToString("yyyy年 MM月 dd日");
				GameFileMD5 = GetFileMD5();
			}
		}

		private string GetInstallPath()
		{
			string exeName = "b1.exe";
			string processName = Path.GetFileNameWithoutExtension(exeName);

			try
			{
				// 获取当前运行的所有进程
				Process[] processes = Process.GetProcessesByName(processName);

				if (processes.Length > 0)
				{
					// 假设取第一个匹配的进程
					Process targetProcess = processes.First();
					string exePath = targetProcess.MainModule.FileName;
					IsGetInstallPath = true;
					// 返回文件所在目录
					return Path.GetDirectoryName(exePath);
				}
				else
				{
					return "获取失败：未找到对应进程。";
				}
			}
			catch (Exception ex)
			{
				// 捕获可能的异常并返回错误信息
				return $"获取失败：{ex.Message}";
			}
		}

		private DateTime GetFileLastModifiedTime()
		{
			string exeName = "b1.exe";
			string processName = Path.GetFileNameWithoutExtension(exeName);

			try
			{
				// 获取当前运行的所有进程
				Process[] processes = Process.GetProcessesByName(processName);

				if (processes.Length > 0)
				{
					Process targetProcess = processes.First();
					string exePath = targetProcess.MainModule.FileName;

					// 获取文件的最后修改时间
					return File.GetLastWriteTime(exePath);
				}
				else
				{
					throw new Exception("未找到对应进程。");
				}
			}
			catch (Exception ex)
			{
				throw new Exception($"获取最后修改时间失败：{ex.Message}");
			}
		}

		private string GetFileMD5()
		{
			string exeName = "b1.exe";
			string processName = Path.GetFileNameWithoutExtension(exeName);

			try
			{
				// 获取当前运行的所有进程
				Process[] processes = Process.GetProcessesByName(processName);

				if (processes.Length > 0)
				{
					Process targetProcess = processes.First();
					string exePath = targetProcess.MainModule.FileName;

					// 计算文件的MD5
					using (var md5 = MD5.Create())
					using (var stream = File.OpenRead(exePath))
					{
						byte[] hash = md5.ComputeHash(stream);
						return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
					}
				}
				else
				{
					throw new Exception("未找到对应进程。");
				}
			}
			catch (Exception ex)
			{
				throw new Exception($"获取文件MD5失败：{ex.Message}");
			}
		}

		public string GetUserGameConfigSavedPath()
		{
			string userProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

			string gameConfigPath = Path.Combine(userProfilePath, "AppData", "Local", "b1");

			if (Directory.Exists(gameConfigPath))
			{
				IsUserGameConfig = true;
				string gameConfigPath2 = Path.Combine(gameConfigPath, "Saved");
				return gameConfigPath2;
			}
			return string.Empty;
		}
	}

	internal class GameSavedPathManage
	{
		private static Dictionary<string, string> savedPaths;

		// 构造函数，初始化字典并加入初始项
		public GameSavedPathManage()
		{
			// 初始化字典
			savedPaths = new Dictionary<string, string>();

			// 预设字典内容
			savedPaths.Add("玩家当前存档", "SaveGames");
			savedPaths.Add("游戏自动备份存档", "SaveGamesBackup");
		}

		// 根据选项名称返回对应的文件路径
		public static string GetFilePathByOptionName(string optionName)
		{
			// 检查字典中是否存在该选项名称
			if (savedPaths.ContainsKey(optionName))
			{
				return savedPaths[optionName]; // 返回对应的文件路径
			}
			else
			{
				return null; // 如果字典中没有该选项，则返回 null 或可以抛出异常
			}
		}

		// 接收 ComboBox 组件并在组件中生成字典项
		public static void PopulateComboBoxWithOptions(ComboBox comboBox)
		{
			// 清空现有的项（如果有的话）
			comboBox.Items.Clear();

			// 遍历字典，将字典的 OptionName 添加到 ComboBox 中
			foreach (var entry in savedPaths)
			{
				comboBox.Items.Add(entry.Key); // 将 OptionName 添加到 ComboBox
			}

			// 可选：选择第一个项为默认选择
			if (comboBox.Items.Count > 0)
			{
				comboBox.SelectedIndex = 0; // 默认选中第一个项
			}
		}
	}

	internal class OpenFilePath 
	{
		public OpenFilePath(string path) 
		{
			if (Directory.Exists(path))
			{
				// 打开文件资源管理器并显示该目录
				Process.Start("explorer.exe", path);
			}
			else
			{
				MessageBox.Show("无效的路径！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
	}

	internal class ReadGameSavedBackupInfo
	{
		private static string csvFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "游戏存档备份信息.csv");

		private static List<BackupInfo> backupData;

		public ReadGameSavedBackupInfo()
		{
			backupData = LoadCsvData();
		}

		// 修改 BackupInfo 类，增加 "备份类型" 字段
		private class BackupInfo
		{
			public string FileName { get; set; }
			public string FileSize { get; set; }
			public string FileMD5 { get; set; }
			public string BackupTime { get; set; }
			public string BackupPath { get; set; }
			public string OriginalPath { get; set; }
			public string BackupType { get; set; } // 新增字段：备份类型
		}

		// 加载 CSV 数据
		private static List<BackupInfo> LoadCsvData()
		{
			var list = new List<BackupInfo>();

			if (File.Exists(csvFilePath))
			{
				var lines = File.ReadAllLines(csvFilePath);

				// 确保文件有数据，跳过第一行（表头）
				for (int i = 1; i < lines.Length; i++)
				{
					var line = lines[i];
					var fields = line.Split(',');

					// 确保每一行有正确的字段（现在有7个字段）
					if (fields.Length >= 7)
					{
						list.Add(new BackupInfo
						{
							FileName = fields[0],
							FileSize = fields[1],
							FileMD5 = fields[2],
							BackupTime = fields[3],
							BackupPath = fields[4],
							OriginalPath = fields[5],
							BackupType = fields[6] // 读取备份类型字段
						});
					}
				}
			}
			else
			{
				throw new FileNotFoundException("CSV 文件不存在: " + csvFilePath);
			}

			return list;
		}

		// 获取指定类型的存档名称列表
		public static List<string> GetGameSavedBackupFileName(string backupType)
		{
			return backupData
				.Where(b => b.BackupType == backupType) // 根据指定类型过滤数据
				.Select(b => b.FileName)
				.ToList();
		}

		// 获取指定存档的大小
		public static string GetGameSavedBackupFileSize(string gameSavedBackupFileName)
		{
			var backupInfo = backupData.FirstOrDefault(b => b.FileName == gameSavedBackupFileName);
			return backupInfo?.FileSize ?? "未找到指定的存档";
		}

		// 获取指定存档的备份时间
		public static string GetGameSavedBackupFileTime(string gameSavedBackupFileName)
		{
			var backupInfo = backupData.FirstOrDefault(b => b.FileName == gameSavedBackupFileName);
			return backupInfo?.BackupTime ?? "未找到指定的存档";
		}

		// 获取指定存档的备份路径
		public static string GetGameSavedBackupFilePath(string gameSavedBackupFileName)
		{
			var backupInfo = backupData.FirstOrDefault(b => b.FileName == gameSavedBackupFileName);
			return backupInfo?.BackupPath ?? "未找到指定的备份路径";
		}

		// 获取指定存档的原文件路径
		public static string GetGameSavedOriginalFilePath(string gameSavedBackupFileName)
		{
			var backupInfo = backupData.FirstOrDefault(b => b.FileName == gameSavedBackupFileName);
			return backupInfo?.OriginalPath ?? "未找到指定的原文件路径";
		}
	}

	internal class WriteGameSavedBackupInfo
	{
		private readonly string _csvFilePath;

		public WriteGameSavedBackupInfo(string savedName, string savedSize, string savedMD5, string backupTime, string backupPath, string originalPath, string backupType)
		{
			// 更新 CSV 表头，增加 "原文件路径" 和 "备份类型" 字段
			string csvHeader = "存档名称,存档大小,存档MD5,备份时间,备份路径,原文件路径,备份类型";
			_csvFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "游戏存档备份信息.csv");

			EnsureCsvFileExists(csvHeader);
			WriteBackupInfo(savedName, savedSize, savedMD5, backupTime, backupPath, originalPath, backupType);
		}

		private void EnsureCsvFileExists(string csvHeader)
		{
			// 如果文件不存在，创建文件并写入表头
			if (!File.Exists(_csvFilePath))
			{
				using (StreamWriter writer = new StreamWriter(_csvFilePath, false))
				{
					writer.WriteLine(csvHeader);
				}
			}
			else
			{
				// 检查文件是否为空或表头不正确
				string firstLine;
				using (StreamReader reader = new StreamReader(_csvFilePath))
				{
					firstLine = reader.ReadLine();
				}

				if (string.IsNullOrWhiteSpace(firstLine) || firstLine.Trim() != csvHeader)
				{
					// 文件为空或表头不正确，重新写入表头
					using (StreamWriter writer = new StreamWriter(_csvFilePath, false))
					{
						writer.WriteLine(csvHeader);
					}
				}
			}
		}

		private void WriteBackupInfo(string savedName, string savedSize, string savedMD5, string backupTime, string backupPath, string originalPath, string backupType)
		{
			// 拼接存档数据为 CSV 格式，增加 "原文件路径" 和 "备份类型" 字段
			string csvRow = $"{savedName},{savedSize},{savedMD5},{backupTime},{backupPath},{originalPath},{backupType}";

			// 追加写入存档数据到 CSV 文件
			using (StreamWriter writer = new StreamWriter(_csvFilePath, true))
			{
				writer.WriteLine(csvRow);
			}
		}
	}

	internal class UnzipFile 
	{
		public UnzipFile(string zipPath, string decompressionPath) 
		{
			try
			{
				if (string.IsNullOrWhiteSpace(zipPath) || string.IsNullOrWhiteSpace(decompressionPath))
				{
					MessageBox.Show("请确保恢复文件路径和程序路径已设置！", "路径错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return;
				}

				// 检查压缩文件是否存在
				if (!File.Exists(zipPath))
				{
					MessageBox.Show("恢复的文件不存在！", "文件错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					return;
				}

				// 解压 ZIP 文件（逐个文件检查是否覆盖）
				using (ZipArchive archive = ZipFile.OpenRead(zipPath))
				{
					foreach (ZipArchiveEntry entry in archive.Entries)
					{
						// 构建目标文件的完整路径
						string destinationPath = Path.Combine(decompressionPath, entry.FullName);

						// 如果目标文件已存在，弹出对话框询问用户是否覆盖
						if (File.Exists(destinationPath))
						{
							DialogResult result = MessageBox.Show(
								$"文件已存在：{destinationPath}\n是否覆盖？",
								"文件已存在",
								MessageBoxButtons.YesNo,
								MessageBoxIcon.Question
							);

							if (result == DialogResult.No)
							{
								// 如果用户选择不覆盖，跳过当前文件
								continue;
							}
						}

						string destinationDirectory = Path.GetDirectoryName(destinationPath);
						if (!Directory.Exists(destinationDirectory))
						{
							Directory.CreateDirectory(destinationDirectory);
						}

						entry.ExtractToFile(destinationPath, true);
					}
				}

				MessageBox.Show("文件恢复完成！", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
			}
			catch (Exception ex)
			{
				// 捕获异常并提示用户
				MessageBox.Show($"文件恢复失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}
	}
}
